#-*- coding:utf8 -*-
import socket
import select
import os
import errno
import Queue
import json
import threading
import time

class Logger:
    m_loggerLock = threading.Lock()

    def __init__(self):
        return
    
    @staticmethod
    def writeLoger(data):
        Logger.m_loggerLock.acquire()
        print "[%s]> %s"%(time.asctime(time.localtime()),data)
        Logger.m_loggerLock.release()

class MsgProcesser:
    def __init__(self,service,dispatchaddr,dispatchport):
        # dispatcher服务端的地址
        self.m_addr = dispatchaddr
        self.m_port = dispatchport
        self.m_sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        # 本processer的服务名
        self.m_service = service
        # 本process的请求入队
        self.m_req_queue = Queue.Queue()
        # 本process的响应队列
        self.m_reply_queue = Queue.Queue()
        
    def register(self):
        self.m_sock.connect((self.m_addr,self.m_port))
        self.m_socklist.append(self.m_sock)
        self.sendMsg("{\"head\":{\"type\":\"manage\"},\"body\":{\"type\":\"register\",\"service\":\"%s\"}}"%(self.m_service))
    
    def closeSock(self):
        self.m_sock.close()
    
    def sendMsg(self,data):
        Logger.writeLoger("send msg:%s"%(data))
        self.m_sock.send(data)
        
    def recvMsg(self):
        # 有 可读 事件激活
        datas = ''
        while True:
            try:
                # 从激活 fd 上 recv 10 字节数据
                data = self.m_sock.recv(1024)
                # 若当前没有接收到数据，并且之前的累计数据也没有
                if not data and not datas:
                # 从 epoll 句柄中移除该 连接 fd
                    self.closeSock()
                    break
                else:
                # 将接收到的数据拼接保存在 datas 中
                    datas += data
                    Logger.writeLoger("%s:%d(fd:%s) receive %s" % (self.m_addr,self.m_port,self.m_sock.fileno(), datas))
                    break
            except socket.error, msg:
                # 在 非阻塞 socket 上进行 recv 需要处理 读穿 的情况
                # 这里实际上是利用 读穿 出 异常 的方式跳到这里进行后续处理
                if msg.errno == errno.EAGAIN or msg.errno == 10035:
                    Logger.writeLoger("[IN] %s:%d(fd:%s) receive %s" % (self.m_addr,self.m_port,self.m_sock.fileno(), datas))
                    # 将已接收数据保存起来
                    break
                else:
                    # 出错处理
                    Logger.writeLoger(msg)
                    self.closeSock()
                    break
        return datas

    def procSock(self,timeout):
        return

    def pushIntoReqQueue(self,data):
        self.m_req_queue.put(data)

    def popFromReqQueue(self,timeout1):
        try:
            data = self.m_req_queue.get(timeout=timeout1)
            return data
        except Exception, e:
            #print e
            return ""

    def pushIntoRespQueue(self,data,fileno):
        self.m_reply_queue.put(data)

    def popFromRespQueue(self,timeout1):
        try:
            data = self.m_reply_queue.get(timeout=timeout1)
            return data
        except Exception, e:
            #print e
            return ""
        
class SelectMsgProcesser(MsgProcesser):
    def __init__(self,service,dispatchaddr,dispatchport):
        MsgProcesser.__init__(self,service,dispatchaddr,dispatchport)
        self.m_socklist = []
    
    def register(self):
        MsgProcesser.register(self)
        self.m_socklist.append(self.m_sock)
    
    def procSock(self,timeout):
        #print self.m_socklist
        rs,ws,es=select.select(self.m_socklist,self.m_socklist,self.m_socklist)
        #if len(rs) > 0 or len(ws) > 0 or len(es) > 0:
        #    print rs
        #    print ws 
        #    print es
        
        for r in rs:
            #print r
            data = self.recvMsg()
            self.pushIntoReqQueue(data)
        #for w in ws:
            #self.sendMsg("")
        for e in es:
            self.closeSock()
        
    def procMsg(self,data,respdata):
        Logger.writeLoger("proc msg:%s"%(data))

    def procMsgFromQueue(self):
        data = self.popFromReqQueue(10)
        if len(data) == 0:
            return
        respdata = ""
        self.procMsg(data,respdata)

def oneProcMsgWorker(msgProc):
    while True:
        msgProc.procMsgFromQueue()

def oneRecvSendWorker(msgProc):
    while True:
        msgProc.procSock(10)
        
def main():
    msgProc = SelectMsgProcesser("myservice","127.0.0.1",1002)
    #msgProc = SelectMsgProcesser("myservice","192.168.0.7",1002)
    msgProc.register()
    workers = []
    for i in range(1):
        w = threading.Thread(target=oneProcMsgWorker, args=(msgProc,))
        workers.append(w)
    w = threading.Thread(target=oneRecvSendWorker, args=(msgProc,))
    workers.append(w)

    for w in workers:
        w.start()

    for w in workers:
        w.join()

if __name__ == '__main__':
    main()
    
